package com.example.grpcserver.config;

import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.health.v1.HealthCheckResponse;
import io.grpc.services.HealthStatusManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import com.example.grpcserver.service.UserServiceImpl;

/**
 * gRPC 服务器启动检查配置
 * 如果使用 Spring Boot gRPC 集成失败，则使用原生 gRPC 启动服务
 */
@Configuration
@Profile("!test") // 非测试环境下启用
public class GrpcServerStartupCheck {

    private static final Logger logger = LoggerFactory.getLogger(GrpcServerStartupCheck.class);
    
    @Value("${grpc.server.port:9090}")
    private int grpcPort;
    
    /**
     * 检查 gRPC 服务是否正确启动，如果没有则使用原生方式启动
     */
    @Bean
    public CommandLineRunner checkGrpcServerStartup() {
        return args -> {
            // 等待 Spring Boot 完全启动
            Thread.sleep(2000);
            
            // 检查端口是否被监听
            boolean isPortOpen = isPortInUse(grpcPort);
            logger.info("检查 gRPC 端口 {} 是否被监听: {}", grpcPort, isPortOpen ? "是" : "否");
            
            if (!isPortOpen) {
                logger.warn("gRPC 服务似乎没有正确启动，尝试使用原生方式启动...");
                startGrpcServerNatively();
            } else {
                logger.info("gRPC 服务已正确启动在端口 {}", grpcPort);
            }
        };
    }
    
    /**
     * 使用原生方式启动 gRPC 服务
     */
    private void startGrpcServerNatively() {
        try {
            // 创建健康检查管理器
            HealthStatusManager healthStatusManager = new HealthStatusManager();
            healthStatusManager.setStatus("", HealthCheckResponse.ServingStatus.SERVING);
            healthStatusManager.setStatus("user.UserService", HealthCheckResponse.ServingStatus.SERVING);
            
            // 构建并启动服务
            Server server = ServerBuilder.forPort(grpcPort)
                    .addService(new UserServiceImpl())
                    .addService(healthStatusManager.getHealthService())
                    .build();
            
            // 在单独的线程中启动服务
            new Thread(() -> {
                try {
                    server.start();
                    logger.info("原生 gRPC 服务已启动在端口 {}", grpcPort);
                    server.awaitTermination();
                } catch (Exception e) {
                    logger.error("原生 gRPC 服务启动失败", e);
                }
            }).start();
            
            // 添加关闭钩子
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                logger.info("关闭原生 gRPC 服务...");
                if (server != null) {
                    server.shutdown();
                }
                logger.info("原生 gRPC 服务已关闭");
            }));
            
        } catch (Exception e) {
            logger.error("启动原生 gRPC 服务失败", e);
        }
    }
    
    /**
     * 检查端口是否被使用
     */
    private boolean isPortInUse(int port) {
        try {
            java.net.Socket socket = new java.net.Socket();
            socket.connect(new java.net.InetSocketAddress("localhost", port), 500);
            socket.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }
} 